using System;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    /// <summary>
    /// 
    /// </summary>
    [TestFixture]
    public class TestDMClassSubClassPropertyNameNotSameAsSuperClassPropertyName
    {
        [SetUp]
        public void SetupTest()
        {
            //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupTest();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            TestUtilsDomain.SetupFixture();
        }

        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
        }

        #region DMClassMustHaveOneProp
        
        [Test]
        public void Test_Contruct()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
        }

        [Test]
        public void Test_Construct_ShouldSupport_IBusinessObjectRule()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Test Result -----------------------
            TestUtilsShared.AssertIsInstanceOf<IBusinessObjectRule>(rule);
        }

        [Test]
        public void Test_Name_ShouldBeCorrect()
        {
            //---------------Set up test pack-------------------
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string name = rule.Name;
            //---------------Test Result -----------------------
            Assert.AreEqual("SubClassPropertyNameNotSameAsSuperClassPropertyName", name);
        }

        [Test]
        public void Test_Error()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Test Result -----------------------
            Assert.AreEqual(ErrorLevel.Warning, rule.ErrorLevel);
        }

//       [Test]
//        public void Test_CreateDMClassSubClassPropertyNameNotSameAsSuperClassPropertyName_WhenClassNull_ShouldRaiseError()
//        {
//            //---------------Set up test pack-------------------
//            //---------------Assert Precondition----------------
//            //---------------Execute Test ----------------------
//            try
//            {
//                new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName(null);
//                Assert.Fail("expected ArgumentNullException");
//            }
//                //---------------Test Result -----------------------
//            catch (ArgumentNullException ex)
//            {
//                StringAssert.Contains("Value cannot be null", ex.Message);
//                StringAssert.Contains("dmClass", ex.ParamName);
//            }
//        }

        [Test]
        public void Test_IsValid_WhenSuperClassRelationshipNull_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmClass.InheritanceSuperClassRelationship);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_WhenSuperClassRelationshipNotNull_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMClass superClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            DMInheritanceRelationship inheritanceRelationship = new DMInheritanceRelationship();
            inheritanceRelationship.SuperClass = superClass;
            inheritanceRelationship.SubClass = dmClass;
            dmClass.CreateDMProp();
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass.InheritanceSuperClassRelationship);
            Assert.IsNotNull(dmClass.InheritanceSuperClassRelationship.SuperClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_WhenBothHaveSamePropName_ShouldFail()
        {
            //---------------Set up test pack-------------------
            DMInheritanceRelationship relationship = TestUtilsDMInheritanceRelationship.CreateUnsavedValidDMInheritanceRelationship();
            DMClass dmClass = relationship.SubClass;
            DMClass superClass = relationship.SuperClass;
            DMProperty dmProperty1 = superClass.CreateDMProp();
            DMProperty dmProperty2 = dmClass.CreateDMProp();
            SetSamePropName(dmProperty1, dmProperty2);
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.AreEqual(2,superClass.Properties.Count, "Prop and Discriminator Prop");
            Assert.AreEqual(1,dmClass.Properties.Count);
            Assert.AreEqual(dmProperty2.PropertyName, dmProperty1.PropertyName);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The SubClass '" + dmClass.ToString() + "' must not have same Property Name '" + dmProperty1.PropertyName + "' as it's SuperClass '" + superClass.ToString() + "'", rule.Message);
        }
        
        [Test]
        public void Test_IsValid_WhenNotSamePropName_ShouldPass()
        {
            //---------------Set up test pack-------------------
            DMInheritanceRelationship relationship = TestUtilsDMInheritanceRelationship.CreateUnsavedValidDMInheritanceRelationship();
            DMClass dmClass = relationship.SubClass;
            DMClass superClass = relationship.SuperClass;
            DMProperty dmProperty1 = superClass.CreateDMProp();
            DMProperty dmProperty2 = dmClass.CreateDMProp();
//            string propertyName = "SuperClassProperty";
            dmProperty1.PropertyName = "SuperClassProperty";
            dmProperty2.PropertyName = "SubClassProperty";
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.AreEqual(2,superClass.Properties.Count, "Prop and discriminator prop");
            Assert.AreEqual(1,dmClass.Properties.Count);
            Assert.AreNotEqual(dmProperty2.PropertyName, dmProperty1.PropertyName);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }
       
        [Test]
        public void Test_IsValid_WhenMoreThanOneLayerHaveSamePropName_ShouldFail()
        {
            //---------------Set up test pack-------------------
            DMInheritanceRelationship relationship = TestUtilsDMInheritanceRelationship.CreateUnsavedValidDMInheritanceRelationship();
            DMClass dmClass = relationship.SubClass;
            DMClass superClass = relationship.SuperClass;
            DMClass grandparentClass = TestUtilsShared.CreateUnsavedValidDMClass();
            superClass.SuperClass = grandparentClass;

            DMProperty dmProperty1 = dmClass.CreateDMProp();
            DMProperty dmProperty2 = superClass.CreateDMProp();
            DMProperty dmProperty3 = grandparentClass.CreateDMProp();

            SetSamePropName(dmProperty1, dmProperty3);
            dmProperty2.PropertyName = TestUtilsShared.GetRandomString();

            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.AreEqual(dmProperty1.PropertyName, dmProperty3.PropertyName);
            Assert.IsTrue(superClass.HasSuperClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The SubClass '" + dmClass.ToString() + "' must not have same Property Name '" + dmProperty1.PropertyName + "' as it's SuperClass '" + superClass.ToString() + "'", rule.Message);
        }

        [Test]
        public void Test_IsValid_WhenMoreThanOneLayerNotSamePropName_ShouldPass()
        {
            //---------------Set up test pack-------------------
            DMInheritanceRelationship relationship = TestUtilsDMInheritanceRelationship.CreateUnsavedValidDMInheritanceRelationship();
            DMClass dmClass = relationship.SubClass;
            DMClass superClass = relationship.SuperClass;
            DMClass grandparentClass = TestUtilsShared.CreateUnsavedValidDMClass();
            superClass.SuperClass = grandparentClass;

            DMProperty dmProperty1 = dmClass.CreateDMProp();
            DMProperty dmProperty2 = superClass.CreateDMProp();
            DMProperty dmProperty3 = grandparentClass.CreateDMProp();

            dmProperty1.PropertyName = TestUtilsShared.GetRandomString();
            dmProperty2.PropertyName = TestUtilsShared.GetRandomString();
            dmProperty3.PropertyName = TestUtilsShared.GetRandomString();
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(dmProperty1.PropertyName, dmProperty2.PropertyName);
            Assert.AreNotEqual(dmProperty1.PropertyName, dmProperty3.PropertyName);
            Assert.IsTrue(superClass.HasSuperClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_WhenSubClassHasSameSuperClassPropNameAndHasMoreThanOneProp_ShouldFail()
        {
            //---------------Set up test pack-------------------
           DMInheritanceRelationship relationship = TestUtilsDMInheritanceRelationship.CreateUnsavedValidDMInheritanceRelationship();
            DMClass dmClass = relationship.SubClass;
            DMClass superClass = relationship.SuperClass;
            DMProperty dmProperty1 = dmClass.CreateDMProp();
            DMProperty dmProperty2 = superClass.CreateDMProp();
            DMProperty dmProperty3 = superClass.CreateDMProp();

            SetSamePropName(dmProperty1, dmProperty3);
            dmProperty2.PropertyName = TestUtilsShared.GetRandomString();
            IBusinessObjectRule rule = new DMClassSubClassPropertyNameNotSameAsSuperClassPropertyName();
            //---------------Assert Precondition----------------
            Assert.AreEqual(3,superClass.Properties.Count, "Prop's and Discriminator Prop");
            Assert.AreEqual(1,dmClass.Properties.Count);
            Assert.AreNotEqual(dmProperty2.PropertyName, dmProperty1.PropertyName);
            Assert.AreEqual(dmProperty3.PropertyName, dmProperty1.PropertyName);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmClass);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The SubClass '" + dmClass.ToString() + "' must not have same Property Name '" + dmProperty1.PropertyName + "' as it's SuperClass '" + superClass.ToString() + "'", rule.Message);
        }

        private void SetSamePropName(DMProperty dmProperty1, DMProperty dmProperty2)
        {
            const string propertyName = "SuperClassProperty";
            dmProperty1.PropertyName = propertyName;
            dmProperty2.PropertyName = propertyName;
        }

        #endregion


    }
}